iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0

模組四|從 2D 到 3D(Day 20–25)

《矽墟》是我正在寫的一部科幻小說,拆成 200 回短篇連載,整部作品用管軟體專案的方式在管:敘事結構寫成規格檔,成品用腳本驗收。

模組三講完 2D 生圖產線。接下來六天是這整個系列的重頭戲:同一個角色,我走了兩條完全不同的 3D 路線,最後選了看起來比較笨的那條。

今天先講為什麼要做這件事,以及一個我覺得比技術選型本身更重要的動作:在看任何方案之前,先把限制寫下來。

問題:一張角色頁,靜態圖不夠

我要替《矽墟》的其中一個角色做一頁獨立的角色誌。

如果只是展示,靜態圖就夠了,我已經有立繪和三視圖,排一排就是一頁。但我想要的不只這些:

  • 能轉。 角色設計裡有一個貫穿全身的道具(一支鐵錨連著鏈與繩),它的空間關係在平面圖上講不清楚。
  • 能換主題色。 這一頁的視覺會隨捲動改變色調,角色要跟著變,不能只有背景在變。

這兩件事都需要 3D。

但限制比需求更需要先寫下來

方案推過來的時候,我自己把那根橫杆往上抬了一截

需求人人都會列。真正決定結果的是限制,而限制最容易在看到漂亮方案的時候被悄悄放寬。

先坦白一件事:下面這三條限制在當時是真的在運作的,但我沒有把它們寫成一份檔案。我為了寫這篇回去翻 repo,只找到 chenger-sculpt-spec.json 裡的品質契約(Day 23 講),沒有任何一份文件列著這三條。

它們存在於我腦子裡。而這篇文章接下來要講的,有一半就是這件事的後果。

三條是:

限制一:純靜態站,零 build step

整個專案沒有 build 流程。index.html 打開就跑,Three.js 從 CDN 用 importmap 載入。

看起來像偷懶,其實是刻意的:一個個人專案最大的死因是環境爛掉。 兩年後我想改一行字,如果要先修好 node 版本、裝回一堆依賴、解決 lockfile 衝突,那我大概就不改了。

所以任何需要編譯、需要打包、需要跑轉檔工具鏈的方案,都要付出這條限制的代價。

限制二:載入預算

這是一頁角色誌,不是遊戲。使用者不會為了看一個角色而等十秒。

我沒有訂一個精確的 KB 數字(後來證明這是個錯誤,Day 22 會講),但心裡的標準是「跟一般網頁差不多」。

限制三:主題色要能即時換

我一直在扳最大那把,真正鎖住的是旁邊那把最小的

改一個變數,模型就跟著變色,不需要重新載入任何資源。

這條限制在當下看起來很小,後來證明它是整個選型的決定性因素。

兩條候選路線

限制寫完之後,才開始看方案。

路線 A:用 image-to-3D 模型生。

我已經有三張三視圖(正面、側面、背面),這正好是 image-to-3D 模型最想要的輸入。丟進去,拿出一個帶貼圖的模型。

聽起來完美。而且 2026 年這類模型的品質已經很好了。

路線 B:把角色拆成基本幾何體,用程式碼堆出來。

球體當頭、旋轉體當和服、圓錐當裙子、環面當鐵錨的環、管狀當繩子。全部用 Three.js 內建的幾何體,一個一個擺上去。

聽起來很土。而且顯然做不到路線 A 的擬真度。

我兩條都做了,但順序跟你想的相反。

實際的時間軸是這樣(檔案與 commit 紀錄):

2026-07-27 14:08   路線 B 的規格檔
2026-07-27 14:51   路線 B 的實作
2026-07-31 14:35   路線 A 的輸入
2026-07-31 15:06   路線 A 的產出

我先做了土的那條,四天後才去試漂亮的那條。

所以別把它讀成「試了最新模型(SOTA)失敗才退回手工」的故事:我已經有一個能跑的東西了,然後才去評估要不要換掉它。而評估的標準因此完全不同:不是「這東西行不行」,是「這東西有沒有好到值得取代現有的」。

接下來的順序我照技術脈絡講而不照時間講:Day 21 講 A 怎麼跑、Day 22 講 A 的產物有什麼問題、Day 23–24 講 B 怎麼做的、Day 25 結算。

先講一個我當時沒做、後來後悔的事

限制沒有落成檔案,也沒有寫成數字。

「載入預算」在我腦子裡是「跟一般網頁差不多」。這句話的問題在於:拿到路線 A 的產物時,我沒辦法用它判定通過還是不通過。

12 MB 算不算「跟一般網頁差不多」?如果我先寫死「模型資產不超過 2 MB」,那 12 MB 就是當場出局,我會省下後面好幾步。

但因為我寫的是模糊的形容詞,所以我做的事情變成「看看能不能壓小一點」,然後在那上面又花了時間。

模糊的限制不會擋住任何東西,它只會在事後讓你覺得「我早就覺得怪怪的」。

這跟 Day 5 講的完全是同一件事:想控制什麼,先讓它可數。 我在敘事規格上做到了(每回 20 句、一章只推進三件事、每章最多一個新名詞),在技術選型上卻沒有。

這一頁最後長什麼樣

先劇透結果,因為它是後面五天的參照點:

chenger.html    865 行    35,119 bytes

整頁 34 KB。 HTML、CSS、JavaScript 全部在裡面,一個檔案,沒有其他外部資源(只有 Three.js 從 CDN 載)。

裡面有 617 行 JavaScript,全部在做同一件事:用基本幾何體把一個角色堆出來。

而路線 A 生出來的那個模型檔案是 13,206,732 bytes。

13,206,732 ÷ 35,119 = 376

那顆模型的大小,是最後上線的整頁的 376 倍。

代價

代價一:兩條路都做,成本是雙倍。

我兩條都跑完才決定,沒有先分析就選邊。這在時間上是浪費的。

比較誠實的說法是:我當時沒有能力光靠分析判斷。 我不知道 image-to-3D 的產物實際上會有哪些問題,那些問題要拿到東西才會浮現。

如果你已經有經驗,你應該可以只走一條。這篇的價值就是讓你少走一條。

代價二:限制沒有落檔,而且太少。

沒落檔的代價是:我今天回去查,只能靠回憶重建它們。一份重建出來的限制清單,永遠有事後合理化的成分,我沒辦法排除「我現在覺得當時在乎的,其實是後來才在乎的」。

就算只算腦子裡的那三條,事後看至少還該有:

  • 可維護性:這個資產之後要改的時候,我改得動嗎?
  • 可量產性:如果 20 個角色都要,這個做法撐得住嗎?
  • 可重跑性:換一台電腦、過半年,我還做得出來嗎?

這三條在 Day 22 全部變成了問題。它們不在我的清單上,所以我在選型的當下完全沒有考慮。

代價三:「能換主題色」這條限制,我當時沒意識到它有多重。

我把它跟另外兩條並排寫,好像三條一樣重。實際上它是最後決定勝負的那一條,因為它直接否定了「貼圖烤死」的方案。(所謂烤死:顏色已經變成貼圖裡的像素,想換主題色就得整張重烤,Day 22 會實際撞到這件事。)

限制清單如果沒有分輕重,你就會在事後才發現哪一條是真正的門檻。

帶走什麼

一、先寫限制,再看方案,而且要真的寫在檔案裡。

看到漂亮的 demo 之後才想限制,你會不自覺地替它找理由。限制要在你對任何方案產生感情之前寫下來。

「寫下來」這三個字我要特別強調,因為我自己沒做到。腦子裡的限制有兩個問題:它可以被悄悄修改而你不會發現,而且事後你無法區分「當時的限制」和「現在的合理化」。

一個 constraints.md,五行字,就解決這兩件事。

二、限制要寫成數字,形容詞擋不住任何東西。

寫成形容詞 寫成數字
載入要快 資產不超過 2 MB
要好維護 改一個顏色不超過 5 分鐘
要能量產 20 個角色的總處理時間不超過 1 天

右邊那些可以當場判定「這個方案出局」。左邊那些只能讓你「有點猶豫」,然後繼續往下走。

三、限制清單至少要涵蓋這四類,缺一類就是一個盲區。

我只寫了第一類,然後在第二、三、四類上全部踩雷:

  1. 當下要能跑(效能、相容、載入)← 大家都會寫
  2. 之後要能改(可維護性)
  3. 之後要能複製(可量產性)
  4. 之後要能重做(可重跑性、環境依賴)

第 1 類是你今天看得到的,第 2–4 類是你三個月後才會痛的。而選型是一次性的決定,三個月後再痛就來不及了。

四、限制之間要排序。

寫完之後問一句:如果只能守住一條,是哪一條?

那一條就是你真正的門檻,其他的是加分項。我的答案是「能換主題色」,而我當時完全沒發現。


明天 Day 21,實際跑路線 A:Microsoft TRELLIS.2,4B 參數的 image-to-3D 模型。三張三視圖進去,一個帶完整 PBR 材質的模型出來。我會講它的核心表示法為什麼能處理衣擺和髮絲這種開放曲面,以及一個對個人創作者很現實的問題:官方要求 24GB 以上的 NVIDIA 顯卡,那沒有的人怎麼辦。


上一篇
Day 19|同一張插圖生了九次,真正的產出是那份文件
下一篇
Day 21|官方要求 24GB 顯卡,我一張都沒有,模型還是跑出來了
系列文
《矽墟》:我把一部科幻小說當成軟體專案來管21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言